/**
 * The Woosta Table Football Engine
 *
 * Released under the terms of the Worcester Public License,
 * see LICENSE for details.
 **
 * Engine Kernel - Buffers
 *
 * Provides template classes for memory managed buffers of
 * any type.
 **
 * Author: Sean Micklethwaite
 **/


#ifndef __bufH__
#define __bufH__

#include "mm.h"


namespace WtfEngine
{
	template <class T, unsigned Size>
	class Buffer : public GcObject
	{
	private:
		T	Data[Size];

	public:
		Buffer() {
			memset(Data, 0, sizeof(T) * Size);
		};

		inline T* getData() {
			return Data;
		};
		inline const T* getData() const {
			return Data;
		};

		inline T& operator [] (unsigned i) {
			assert(i < Size);
			return Data[i];
		};
		inline const T& operator [] (unsigned i) const {
			assert(i < Size);
			return Data[i];
		};

		GC_AUTOSIZE(Buffer);
	};

	
	/**
	 * This class allows arbitrary blocks of memory to be passed around
	 * and shared safely, without the need for copying.
	 **/
	template <class T = unsigned char>
	class NonCopyBuffer : public GcObject
	{
	private:
		T *			Data;
		unsigned	Count;

	public:
		/// New buffer of size c allocated
		NonCopyBuffer(unsigned c)
			: Data(new T[c]), Count(c) {
		};
		/// Buffer takes ownership of the passed data
		/// @warning Use the const version to copy the buffer.
		NonCopyBuffer(T * pData, unsigned c)
			: Data(pData), Count(c) {
		};
		/// Here we must copy, as the passed buffer cannot be
		/// modified.
		NonCopyBuffer(const T * pData, unsigned c)
		: Data(new T[c]), Count(c) {
			for(int i = 0; i < c; i++) {
				Data[i] = pData[i];
			};
		};
		~NonCopyBuffer() {
			delete [] Data;
		};

		inline T* getData() {
			return Data;
		};
		inline const T* getData() const {
			return Data;
		};
		inline unsigned getCount() const {
			return Count;
		};

		inline T& operator [] (unsigned i) {
			assert(i < Count);
			return Data[i];
		};
		inline const T& operator [] (unsigned i) const {
			assert(i < Count);
			return Data[i];
		};

		GC_OBJECT(NonCopyBuffer, sizeof(NonCopyBuffer) + (sizeof(T) * Count));
	};
};

#endif
